package com.dhcc.core.framework.beetl.resource;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.URL;

import org.beetl.core.Resource;
import org.beetl.core.ResourceLoader;
import org.beetl.core.exception.BeetlException;

public class BeetlResource extends Resource {

    private File file = null;
    private String path = null;
    private long lastModified = 0;
    private boolean isClassLoader = true;

    public BeetlResource(File file, String key, ResourceLoader loader) {
        super(key, loader);
        this.file = file;
        this.lastModified = file.lastModified();
        this.isClassLoader = false;
    }

    public BeetlResource(String key, String path, ResourceLoader resourceLoader) {
        super(key, resourceLoader);
        this.path = path;
        this.isClassLoader = true;
    }

    @Override
    public Reader openReader() {
        BeetlResourceLoader loader = (BeetlResourceLoader) this.getResourceLoader();
        if (isClassLoader) {
            return classLoaderOpenReader(loader);
        }
        return fileOpenReader(loader);
    }

    @Override
    public boolean isModified() {
        if (file != null) {
            return file.lastModified() != this.lastModified;
        } else {
            return true;
        }
    }

    public Reader fileOpenReader(BeetlResourceLoader loader) {
        Reader br;
        try {
            br = new BufferedReader(new InputStreamReader(new FileInputStream(file), loader.getCharset()));
        } catch (UnsupportedEncodingException e) {
            return null;
        } catch (FileNotFoundException e) {
            BeetlException be = new BeetlException(BeetlException.TEMPLATE_LOAD_ERROR,
                    " 模板根目录为 " + loader.getRootPath());
            be.pushResource(this);
            throw be;

        }
        return br;
    }

    public Reader classLoaderOpenReader(BeetlResourceLoader loader) {
        ClassLoader cs = loader.getClassLoader();
        URL url = cs.getResource(path);
        if (url == null) {
            // 兼容以前的写法
            url = resourceLoader.getClass().getResource(path);
        }

        if (url == null) {
            BeetlException be = new BeetlException(BeetlException.TEMPLATE_LOAD_ERROR);
            be.pushResource(this);
            throw be;
        }
        InputStream is;
        try {
            is = url.openStream();
        } catch (IOException e1) {
            BeetlException be = new BeetlException(BeetlException.TEMPLATE_LOAD_ERROR);
            be.pushResource(this);
            throw be;
        }

        if (is == null) {
            BeetlException be = new BeetlException(BeetlException.TEMPLATE_LOAD_ERROR);
            be.pushResource(this);
            throw be;
        }

        if ("file".equals(url.getProtocol())) {
            try {
                file = new File(java.net.URLDecoder.decode(url.getFile(), "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException(e);
            }
            lastModified = file.lastModified();
        }

        Reader br;
        try {
            br = new BufferedReader(new InputStreamReader(is, loader.getCharset()));
            return br;
        } catch (UnsupportedEncodingException e) {
            return null;
        }
    }

    /**
     * @param file the file to set
     */
    public void setFile(File file) {
        this.file = file;
    }

    /**
     * @return String return the path
     */
    public String getPath() {
        return path;
    }

    /**
     * @param path the path to set
     */
    public void setPath(String path) {
        this.path = path;
    }

    /**
     * @return long return the lastModified
     */
    public long getLastModified() {
        return lastModified;
    }

    /**
     * @param lastModified the lastModified to set
     */
    public void setLastModified(long lastModified) {
        this.lastModified = lastModified;
    }

    /**
     * @return boolean return the isClassLoader
     */
    public boolean getIsClassLoader() {
        return isClassLoader;
    }

    /**
     * @param isClassLoader the isClassLoader to set
     */
    public void setIsClassLoader(boolean isClassLoader) {
        this.isClassLoader = isClassLoader;
    }

}